#ifndef __MY_MYSQL_H__
#define __MY_MYSQL_H__
#include <mysql/mysql.h>
#include <string>
#include <stdexcept>
#include <memory>
#include <mutex>
#include "Log.hpp"
using namespace LogModule;

// 自定义异常类，保持不变
class MySqlClientException : public std::runtime_error
{
public:
    explicit MySqlClientException(const std::string &message)
        : std::runtime_error("MySqlClientException: " + message) {}
};

class MySqlResult
{
public:
    MySqlResult(MYSQL_RES *res = nullptr)
        : _res(res)
    {
    }

    size_t RowNum() const
    {
        if (!_res)
            throw MySqlClientException("MySqlResult::RowNum: 非法的结果集!");
        return mysql_num_rows(_res);
    }

    size_t FieldNum() const
    {
        if (!_res)
            throw MySqlClientException("MySqlResult::FieldNum: 非法的结果集!");
        return mysql_num_fields(_res);
    }

    MYSQL_ROW NextRow()
    {
        if (!_res)
            return nullptr; // 避免无效访问
        return mysql_fetch_row(_res);
    }

    MYSQL_FIELD *NextField()
    {
        if (!_res)
            return nullptr; // 避免无效访问
        return mysql_fetch_field(_res);
    }

    ~MySqlResult()
    {
        if (_res != nullptr)
        {
            mysql_free_result(_res);
            _res = nullptr;
        }
    }

    // 禁用拷贝构造和赋值运算符
    MySqlResult(const MySqlResult &) = delete;
    MySqlResult &operator=(const MySqlResult &) = delete;

    // 支持移动语义
    MySqlResult(MySqlResult &&other) noexcept : _res(other._res)
    {
        other._res = nullptr;
    }
    MySqlResult &operator=(MySqlResult &&other) noexcept
    {
        if (this != &other)
        {
            _res = other._res;
            other._res = nullptr;
        }
        return *this;
    }

private:
    MYSQL_RES *_res = nullptr;
};

class MySqlClient
{
public:
    MySqlClient(const std::string &host,
                const std::string &user,
                const std::string &passwd,
                const std::string &db,
                unsigned int port = 3306)
        : _mysql(mysql_init(nullptr))
    {
        if (!_mysql)
        {
            throw MySqlClientException("mysql句柄初始化失败!");
        }

        // 处理空字符串参数
        const char *host_ptr = host.empty() ? nullptr : host.c_str();
        const char *db_ptr = db.empty() ? nullptr : db.c_str();

        if (!mysql_real_connect(_mysql, host_ptr, user.c_str(), passwd.c_str(),
                                db_ptr, port, nullptr, 0))
        {
            std::string err = mysql_error(_mysql);
            mysql_close(_mysql); // 连接失败时释放已初始化的_mysql
            _mysql = nullptr;
            throw MySqlClientException("连接到mysql服务器失败: " + err);
        }

        // 使用utf8mb4支持完整UTF-8
        if (mysql_set_character_set(_mysql, "utf8mb4") != 0)
        {
            std::string err = mysql_error(_mysql);
            mysql_close(_mysql);
            _mysql = nullptr;
            throw MySqlClientException("设置字符集失败: " + err);
        }
    }

    // 执行SQL，返回：<影响行数（或结果集行数）, 结果集（若有）>
    std::pair<size_t, std::shared_ptr<MySqlResult>> Query(const std::string &sql)
    {
        if (!_mysql)
            throw MySqlClientException("Query: 非法的mysql客户端句柄!");

        // 查询的过程上锁，避免结果被其他线程的查询结果覆盖
        std::unique_lock<std::mutex> lockguard(_mtx);
        // 执行SQL，检查是否失败
        int query_ret = mysql_query(_mysql, sql.c_str());
        if (query_ret != 0)
        {
            LOG(LogLevel::ERROR) << "Query: [" << sql << "]查询失败! " << mysql_error(_mysql);
            return std::make_pair<size_t, std::shared_ptr<MySqlResult>>(0, nullptr);
        }

        std::pair<size_t, std::shared_ptr<MySqlResult>> ret;

        // 判断是否有结果集（如SELECT、SHOW等）
        if (mysql_field_count(_mysql) != 0)
        {
            MYSQL_RES *res = mysql_store_result(_mysql);
            if (!res)
            {
                // 若预期有结果集但获取失败（如内存不足）
                throw MySqlClientException("获取结果集失败: " + std::string(mysql_error(_mysql)));
            }
            ret.second = std::make_shared<MySqlResult>(res);
            ret.first = ret.second->RowNum(); // 结果集行数
        }
        else
        {
            // 无结果集，返回影响行数
            ret.first = static_cast<size_t>(mysql_affected_rows(_mysql));
            ret.second = nullptr;
        }
        return ret;
    }

    ~MySqlClient()
    {
        if (_mysql != nullptr) // 仅在有效时关闭
        {
            mysql_close(_mysql);
            _mysql = nullptr;
        }
    }

    // 禁用拷贝构造和赋值运算符
    MySqlClient(const MySqlClient &) = delete;
    MySqlClient &operator=(const MySqlClient &) = delete;

    // 支持移动语义（可选）
    MySqlClient(MySqlClient &&other) noexcept : _mysql(other._mysql)
    {
        other._mysql = nullptr;
    }
    MySqlClient &operator=(MySqlClient &&other) noexcept
    {
        if (this != &other)
        {
            _mysql = other._mysql;
            other._mysql = nullptr;
        }
        return *this;
    }

private:
    MYSQL *_mysql = nullptr;
    std::mutex _mtx;
};

#endif